import poser, os, sys, string, re

os.chdir( os.path.dirname(poser.AppLocation()) )

ffAuto0 = { 'minShadingRate' : 4.00, 'doShadows' : 0, 'pixelSamples' : 1, 'allowRayTracing' : 0, 'maxRayDepth' : 0, 'useSumAreaTables' : 0, 'maxTextureRes' : 512 }
ffAuto1 = { 'minShadingRate' : 2.00, 'doShadows' : 0, 'pixelSamples' : 2, 'allowRayTracing' : 0, 'maxRayDepth' : 0, 'useSumAreaTables' : 0, 'maxTextureRes' : 768 }
ffAuto2 = { 'minShadingRate' : 1.50, 'doShadows' : 0, 'pixelSamples' : 2, 'allowRayTracing' : 0, 'maxRayDepth' : 0, 'useSumAreaTables' : 0, 'maxTextureRes' : 1024 }
ffAuto3 = { 'minShadingRate' : 1.25, 'doShadows' : 1, 'pixelSamples' : 3, 'allowRayTracing' : 0, 'maxRayDepth' : 0, 'useSumAreaTables' : 0, 'maxTextureRes' : 1280 }
ffAuto4 = { 'minShadingRate' : 1.00, 'doShadows' : 1, 'pixelSamples' : 3, 'allowRayTracing' : 1, 'maxRayDepth' : 1, 'useSumAreaTables' : 0, 'maxTextureRes' : 1536 }
ffAuto5 = { 'minShadingRate' : 0.75, 'doShadows' : 1, 'pixelSamples' : 3, 'allowRayTracing' : 1, 'maxRayDepth' : 2, 'useSumAreaTables' : 0, 'maxTextureRes' : 2048 }
ffAuto6 = { 'minShadingRate' : 0.60, 'doShadows' : 1, 'pixelSamples' : 3, 'allowRayTracing' : 1, 'maxRayDepth' : 3, 'useSumAreaTables' : 0, 'maxTextureRes' : 2560 }
ffAuto7 = { 'minShadingRate' : 0.50, 'doShadows' : 1, 'pixelSamples' : 3, 'allowRayTracing' : 1, 'maxRayDepth' : 4, 'useSumAreaTables' : 1, 'maxTextureRes' : 3584 }
ffAuto8 = { 'minShadingRate' : 0.10, 'doShadows' : 1, 'pixelSamples' : 6, 'allowRayTracing' : 1, 'maxRayDepth' : 6, 'useSumAreaTables' : 1, 'maxTextureRes' : 4096 }

ffAuto = [ffAuto0, ffAuto1, ffAuto2, ffAuto3, ffAuto4, ffAuto5, ffAuto6, ffAuto7, ffAuto8]

class engineOptions:
	def __init__(self):
		self.defaults = self.defaultOptions()
		self.options = self.defaults
		self.wipeValues()
		self.usePreset = 0
		self.code = self.engineCode()
		self.raw = ""
	def wipeValues(self):
		for key in self.options.keys():
			self.options[key] = "USEDOC"		
	def engineCode(self):
		return 92
	def getDefault(self, option):
		return self.defaults[option]
	def defaultOptions(self):
		return {}
	def load(self, presetFile):
		self.usePreset = presetFile
	def set(self, opts):
		for k, v in opts.items():
			self.setFlag(k, v)
	def setFlag(self, flag, value):
		self.options[flag] = value
	def get(self, opt):
		return self.options[opt]
	def getOptions(self):
		return self.options
	def setToSceneOpts(self, scene):
		pass

class docSettings(engineOptions):
	def defaultOptions(self):
		return {}

class movieSettings(engineOptions):
	def defaultOptions(self):
		return {
				'outputStartFrame' : 0,
				'outputEndFrame' : 29,
				'antiAlias' : 'false',
			}
	def setOutputRange(self, start, end):
		self.options['outputStartFrame'] = repr(start)
		self.options['outputEndFrame'] = repr(end)

class generalSettings(engineOptions):
	def defaultOptions(self):
		return {
				'newWinWidth' : 640,
				'newWinHeight' : 480,
				'autoScaleToView' : 0,
				'newWinDPI' : 72,
				'useRenderer' : 'p5',
				'reuseShadowMaps' : 0,
			}
	def setRenderer(self, engineCode):
		if engineCode == poser.kRenderEngineCodeFIREFLY:
			self.options['useRenderer'] = 'p5'
		elif engineCode == poser.kRenderEngineCodePOSER4:
			self.options['useRenderer'] = 'p4'
		elif engineCode == poser.kRenderEngineCodeSKETCH:
			self.options['useRenderer'] = 'sketch'
		elif engineCode == 3:
			self.options['useRenderer'] = 'preview'
		elif engineCode == 92:
			self.options['useRenderer'] = 'USEDOC'
		else:
			raise "Unknown render engine id: %s" % repr(engineCode)
	def setOutputRes(self, width, height):
		self.set({'newWinWidth':width, 'newWinHeight':height})
		self.renderToNewWindow(1)
	def renderToNewWindow(self, bool):
		if bool:
			self.set({'autoScaleToView':'0'})
		else:
			self.set({'autoScaleToView':'2'})
	def reuseShadowMaps(self, bool):
		self.options['reuseShadowMaps'] = repr(bool)

class fireFly(engineOptions):
	def defaultOptions(self):
		return {
				'auto' : 0,
				'autoValue' : 2,
				'shadowRenderShadingRate' : 16,
				'maxRayDepth' : 4,
				'filterSize' : 1,
				'filterType' : 0,
				'pixelSamples' : 3,
				'bucketSize' : 64,
				'motionSamples' : 1,
				'allowRayTracing' : 0,
				'minShadingRate' : 0.5,
				'maxTextureRes' : 1024,
				'hairShadingRate' : 8.0,
				'doShadows' : 1,
				'smoothPolys' : 0,
				'backfaceCull' : 0,
				'allowDisplacement' : 1,
				'drawToonOutline' : 0,
				'toonOutlineStyle' : 3,
				'shadowOnlyRender' : 0,
				'useP5renderer' : 1,
				'motionBlur' : 0,
				'useDOF' : 0,
				'useSumAreaTables' : 0,
				'minDisplacementBounds' : 0.0,
				}
	def getSceneOpts(self, scene):
		ff = scene.CurrentFireFlyOptions()
		ffOpts = {
				'maxRayDepth' : ff.MaxRayDepth(),
				'filterSize' : ff.FilterSize(),
				'filterType' : ff.FilterType(),
				'pixelSamples' : ff.PixelSamples(),
				'bucketSize' : ff.BucketSize(),
				'allowRayTracing' : ff.RayTracing(),
				'minShadingRate' : ff.MinShadingRate(),
				'maxTextureRes' : ff.MaxTextureRes(),
				'doShadows' : ff.Shadows(),
				'smoothPolys' : ff.SmoothPolys(),
				'allowDisplacement' : ff.Displacement(),
				'drawToonOutline' : ff.DrawToonOutline(),
				'toonOutlineStyle' : ff.ToonOutlineStyle(),
				'shadowOnlyRender' : ff.ShadowOnlyRender(),
				'useP5renderer' : 1,
				'motionBlur' : ff.MotionBlur(),
				'useDOF' : ff.DepthOfField(),
				'useSumAreaTables' : ff.TextureFiltering(),
				'minDisplacementBounds' : ff.DisplacementBounds(),
				}
		if ff.Manual():
			return ffOpts
		else:
			ffOpts.update( ffAuto[ff.AutoValue()] )
			return ffOpts
	def setToSceneOpts(self, scene):
		self.set( self.getSceneOpts(scene) )
		self.setFlag('auto', 1)
	def engineCode(self):
		return poser.kRenderEngineCodeFIREFLY
	def load(self, presetFile):
		fi = open(presetFile, 'r')
		preset = fi.readlines()
		fi.close()
		opts = {}
		storeLines = 0
		for line in preset:
			if not line: continue
			if re.search("settings",line):
				storeLines = 1
				continue
			elif storeLines and re.search("\{",line):
				continue
			elif storeLines and re.search("\}",line):
				storeLines = 0
				break
			elif storeLines:
				key, val = string.split(string.strip(line))
				opts[key] = val
			else:
				continue
		self.set(opts)

class poser4(engineOptions):
	def defaultOptions(self):
		return {
				'antialiasing' : 1,
				'useTexture' : 1,
				'useBump' : 1,
				'castShadows' : 1,
			}
	def engineCode(self):
		return poser.kRenderEngineCodePOSER4

class poserSketch(engineOptions):
	def engineCode(self):
		return poser.kRenderEngineCodeSKETCH
	def load(self, presetFile):
		fi = open(presetFile, 'r')
		preset = fi.readlines()
		fi.close()
		stored = []
		storeLines = 0
		levelsIn = 0
		for line in preset:
			if not line: continue
			if re.search("illustrationParms",line):
				storeLines = 1
				stored.append(line)
			elif storeLines and re.search("\{",line):
				stored.append(line)
				levelsIn = levelsIn + 1
			elif storeLines and re.search("\}",line):
				stored.append(line)
				levelsIn = levelsIn - 1
				if levelsIn == 0:
					storeLines = 0
					break
			elif storeLines:
				stored.append(line)
			else:
				continue
		self.raw = string.join(stored,"")

class poserPreview(engineOptions):
	def engineCode(self):
		return 3

class cm2Builder:
	def __init__(self):
		self.cm2 = """{\n\nversion\n\t{\n\tnumber 6\n\t}"""
		self.raw = ""
	def add(self, text):
		self.cm2 = self.cm2 + text
	def str(self, obj):
		return string.replace( repr(obj), "'", "")
	def addOption(self, option, value):
		self.add( "\n\t" + option + " " + self.str(value) )
	def addFFOption(self, option, value):
		self.add( "\n\t\t" + option + " " + self.str(value) )
	def openRender(self):
		self.add( "\nrenderDefaults\n\t{" )
	def closeRender(self):
		self.add( "\n\t}" )
	def openSettings(self):
		self.add( "\n\tsettings\n\t\t{" )
	def closeSettings(self):
		self.add( "\n\t\t}" )
	def openDoc(self):
		self.add( "\ndoc\n\t{" )
	def closeDoc(self):
		self.add( "\n\t}" )
	def setCamera(self, camera="USEDOC"):
		if camera != "USEDOC": self.add( "\n\tuseCamera %s" % camera )
	def setDoc(self, docOpts):
		for key, val in docOpts.items():
			if val == "USEDOC": continue
			self.addOption(key, val)
	def setPoser4(self, p4Opts):
		for key, val in p4Opts.items():
			if val == "USEDOC": continue
			self.addOption(key, val)
	def setFireFly(self, ffOpts):
		self.openSettings()
		for key, val in ffOpts.items():
			if val == "USEDOC": continue
			self.addFFOption(key, val)
		self.closeSettings()
	def setSketch(self, sk):
		self.setRaw(sk)
	def setPreview(self, pv):
		self.setRaw(pv)
	def setRaw(self, raw):
		if raw: self.raw = self.raw + raw
	def setMovieOpts(self, movie={}):
		self.add( "\nmovieInfo\n\t{" )
		for opt, val in movie.items():
			if val == "USEDOC": continue
			self.addOption(opt, val)
		self.add( "\n\t}" )
	def setRenderOpts(self, general={}, poser4={}, fireFly={}):
		self.openRender()
		self.setPoser4(general)
		self.setPoser4(poser4)
		self.setFireFly(fireFly)
		self.closeRender()
	def setDocOpts(self, doc={}):
		self.openDoc()
		self.setDoc(doc)
		self.closeDoc()
	def close(self):
		self.add( "\n" + self.raw )
		self.add( "\n}" )
	def get(self):
		return self.cm2

def makeCm2(camera="USEDOC", docOptions={}, movieOptions={}, generalOptions={}, poser4Options={}, fireFlyOptions={}, sketchOptions=None, previewOptions=None, rawOptions=None):
	cm2 = cm2Builder()
	docOptions["useCamera"] = camera
	cm2.setDocOpts( doc=docOptions )
	cm2.setMovieOpts( movie=movieOptions )
	cm2.setRenderOpts( general=generalOptions, poser4=poser4Options, fireFly=fireFlyOptions )
	cm2.setSketch(sketchOptions)
	cm2.setPreview(previewOptions)
	cm2.setRaw(rawOptions)
	cm2.close()
	return cm2.get()

def writeFile(outFile, data):
	fi = open(outFile, 'w')
	fi.write(data)
	fi.close()
	return outFile

class renderSettings:
	def __init__(self, engine, movie=movieSettings()):
		self.camera = "USEDOC"
		self.engine = engine
		self.doc = docSettings()
		self.movie = movie
		self.general = generalSettings()
		self.tempFile = "gwrTemp.cm2"
		self.isBaked = 0
	def setEngine(self, engine):
		self.engine = engine
	def forceManual(self, scene):
		self.apply(scene)
		self.engine.setToSceneOpts( scene )
	def engineType(self):
		return self.engine.code
	def engineOptions(self):
		return self.engine.getOptions()
	def engineFile(self):
		return self.engine.usePreset
	def bakeSettings(self, outFile):
		self.general.setRenderer(self.engineType())
		if self.engineType() == poser.kRenderEngineCodeFIREFLY:
			ff, p4, sk, pv = self.engineOptions(), {}, None, None
		elif self.engineType() == poser.kRenderEngineCodePOSER4:
			ff, p4, sk, pv = {}, self.engineOptions(), None, None
		elif self.engineType() == poser.kRenderEngineCodeSKETCH:
			ff, p4, sk, pv = {}, {}, self.engine.raw, None
		elif self.engineType() == 3:
			ff, p4, sk, pv = {}, {}, None, self.engine.raw
		else:
			ff, p4, sk, pv = {}, {}, None, None
		cm2 = makeCm2(docOptions=self.doc.options, movieOptions=self.movie.options, generalOptions=self.general.options, poser4Options=p4, fireFlyOptions=ff, sketchOptions=sk, previewOptions=pv)
		writeFile(outFile, cm2)
		self.isBaked = 1
	def apply(self, scene):
		#if not self.isBaked: self.bakeSettings(self.tempFile)
		self.bakeSettings(self.tempFile)
		scene.LoadLibraryCamera(self.tempFile)
		self.setCamera(scene)
	def cleanup(self):
		try: os.remove(self.tempFile)
		except: pass
		self.isBaked = 0
	def docFlag(self, flag, value):
		self.doc.setFlag(flag, value)
	def movieFlag(self, flag, value):
		self.movie.setFlag(flag, value)
	def genFlag(self, flag, value):
		self.general.setFlag(flag, value)
	def setFlag(self, flag, value):
		self.engine.setFlag(flag, value)
	def setOutputRange(self, start, end):
		self.movie.setOutputRange(start, end)
	def setOutputRes(self, width, height):
		self.general.setOutputRes(width, height)
	def reuseShadowMaps(self, bool):
		self.general.reuseShadowMaps(bool)
	def setCamera(self, scene):
		if self.camera != "USEDOC":
			scene.SetCurrentCamera(scene.ActorByInternalName(self.camera))

def engineByCode(ec):
	if ec == poser.kRenderEngineCodeFIREFLY:
		return fireFly()
	elif ec == poser.kRenderEngineCodePOSER4:
		return poser4()
	elif ec == poser.kRenderEngineCodeSKETCH:
		return poserSketch()
	elif ec == 3:
		return poserPreview()
	elif ec == 92:
		return engineOptions()
	else:
		raise "Bad engine code: %i" % ec

rsFireFly = renderSettings( fireFly() )
rsPoser4 = renderSettings( poser4() )
rsSketch = renderSettings( poserSketch() )
rsPreview = renderSettings( poserPreview() )
genericRS = renderSettings( engineOptions() )

if __name__ == '__main__':
	ff = fireFly()
	sk = poserSketch()
	p4 = poser4()
	pv = poserPreview()
	#ff.load( os.path.join("Runtime","prefs","RenderPresets","Super Good.prp") )
	#sk.load( os.path.join("Runtime","prefs","SketchPresets","Colored.pzs") )
	rs = renderSettings(ff)
	rs.forceManual(poser.Scene())
	#rs.setOutputRange(0, 39)
	#rs.setOutputRes(512,384)
	#rs.reuseShadowMaps(1)
	#rs.camera = "AUX_CAMERA"
	#rs.apply(poser.Scene())
	#rs.cleanup()

	print ff.getSceneOpts(poser.Scene())
pass